home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UCRASM25.ARJ / PRINTFF.ASM < prev    next >
Assembly Source File  |  1991-11-22  |  17KB  |  831 lines

  1. StdGrp        group    stdlib,stddata
  2. stddata        segment    para public 'sldata'
  3.         extrn    fpacc:word
  4. stddata        ends
  5. ;
  6. stdlib        segment    para public 'slcode'
  7.         assume    cs:stdgrp
  8. ;
  9.         extrn    sl_Putc:far, sl_Puti:far, sl_ISize:far
  10.         extrn    sl_Putw:far, sl_Puth:far
  11.         extrn    sl_Putu:far, sl_PutUL:far, sl_ULSize:far
  12.         extrn    sl_LSize:far, sl_USize:far, sl_PutL:far
  13.         extrn    sl_pute:far, sl_putf:far
  14.         extrn    sl_LSFPA:far, sl_LDFPA:far, sl_LEFPA:far
  15. ;
  16. ;
  17. putc        equ    sl_putc
  18. puti        equ    sl_puti
  19. ISize        equ    sl_ISize
  20. putw        equ    sl_putw
  21. puth        equ    sl_puth
  22. putu        equ    sl_putu
  23. putul        equ    sl_putul
  24. ulsize        equ    sl_ulsize
  25. lsize        equ    sl_lsize
  26. usize        equ    sl_usize
  27. putl        equ    sl_putl
  28. putf        equ    sl_putf
  29. pute        equ    sl_pute
  30. ;
  31. ;
  32. ; Printff- Like Printf except this guy supports floating point values too.
  33. ;       A program should not include both printf and printff.  Printff
  34. ;       includes everything printf does an more.  Including them both
  35. ;       would waste a lot of memory.  There are two routines because
  36. ;       most people don't need floating point I/O and printff links in
  37. ;       the floating point package which is quite large.
  38. ;
  39. ;               call    printf
  40. ;               db      "format string",0
  41. ;               dd      item1, item2, ..., itemn
  42. ;
  43. ; The format string is identical to "C".  Item1..Itemn are pointers to
  44. ; values to print for this string.  Each item must be matched by the
  45. ; corresponding "%xxx" item in the format string.
  46. ;
  47. ; Format string format:
  48. ;
  49. ; 1)    All characters, except the following, are printed to the standard
  50. ;       output as-is.
  51. ;
  52. ; 2)    "\" is the escape character.  Anything following it is printed
  53. ;       as-is except standard "C" values like \r, \n, \b, \t, etc.  If
  54. ;       a decimal digit follows the back-slash, printf assumes that this
  55. ;       is a hexadecimal number and converts following three digits to
  56. ;       an ASCII character and prints it.  Other back-slash operators are
  57. ;       just like those for "C".
  58. ;
  59. ; 3)    Format Control Strings:
  60. ;
  61. ;    General format:  "%s\cn^f" where:
  62. ;                s = -
  63. ;                n = a decimal integer or two integers
  64. ;                    separated by a period (for fp).
  65. ;                c = a fill character
  66. ;                ^ = ^
  67. ;                f = a format character
  68. ;
  69. ;            All fields except "%" and "f" are optional.
  70. ;
  71. ;    s = -       Left justify value and use fill character.
  72. ;    \c present    Use "c" as fill character.
  73. ;    n present    Use "n" as the minimum field width.
  74. ;    ^ present    The address associated with f is the address of a
  75. ;                pointer to the object, not the address of
  76. ;                the object itself.  The pointer is a far ptr.
  77. ;
  78. ;    f is one of the following
  79. ;
  80. ;        d -    Print signed integer in decimal notation.
  81. ;        i -    Print signed integer in decimal notation.
  82. ;        x -    Print word value in hexadecimal notation.
  83. ;        h -    Print byte value in hexadecimal notation.
  84. ;        u -    Print unsigned integer in decimal notation.
  85. ;        c -    Print character.
  86. ;        s -    Print string.
  87. ;        f -    Print floating point number in decimal form.
  88. ;         e -    Print floating point number in scientific notation.
  89. ;
  90. ;        ld-    Print long signed integer.
  91. ;        li-    Print long unsigned integer.
  92. ;        lx-    Print long hexadecimal number.
  93. ;        lu-    Print long unsigned number.
  94. ;        lf-    Print dbl prec fp number in decimal form.
  95. ;        le-    Print dbl prec fp number in scientific notation.
  96. ;
  97. ;        gf-    Print extended precision fp number in decimal form.
  98. ;        ge-    Print extended precision fp number in sci not form.
  99. ;
  100. ;
  101. ;    Calling Sequence:
  102. ;
  103. ;        call    Printf
  104. ;        db    "Format String",0
  105. ;        dd    adrs1, adrs2, ..., adrsn
  106. ;
  107. ;    Where the format string is ala "C" (and the descriptions above)
  108. ;    and adrs1..adrsn are addresses (far ptr) to the items to print.
  109. ;    Unless the "^" modifier is present, these addresses are the actual
  110. ;    addresses of the objects to print.
  111. ;
  112. ;
  113. ;
  114. cr        equ    0dh
  115. ff        equ    0ch
  116. lf        equ    0ah
  117. tab        equ    09h
  118. bs        equ    08h
  119. ;
  120. RtnAdrs        equ    2[bp]
  121. ;
  122.         public  sl_printff
  123. sl_printff    proc    far
  124.         push    bp
  125.         mov    bp, sp
  126.         pushf
  127.         push    ax
  128.         push    bx
  129.         push    cx
  130.         push    dx
  131.         push    di
  132.         push    si
  133.         push    es
  134.         push    ds
  135. ;
  136. ; Get pointers to the return address (format string).
  137.         cld
  138.         les    di, RtnAdrs
  139.         lds    si, RtnAdrs
  140. ;
  141. ; Okay, search for the end of the format string.  After these instructions,
  142. ; di points just beyond the zero byte at the end of the format string.  This,
  143. ; of course, points at the first address beyond the format string.
  144. ;
  145.         mov    al, 0
  146.         mov    cx, 65535
  147.     repne    scasb
  148. ;
  149. PrintItems:    lodsb            ;Get char si points at.
  150.         cmp    al, 0        ;EOS?
  151.         jz    PrintfDone
  152.         cmp    al, "%"        ;Start of a format string?
  153.         jz    FmtItem
  154.         cmp    al, "\"        ;Escape character?
  155.         jnz    PrintIt
  156.         call    GetEscChar
  157. PrintIt:    call    Putc
  158.         jmp    PrintItems
  159. ;
  160. FmtItem:    call    GetFmtItem    ;Process the format item here.
  161.         jmp    PrintItems
  162. ;
  163. PrintfDone:    mov    RtnAdrs, di    ;Put out new return address.
  164.         pop    ds
  165.         pop    es
  166.         pop    si
  167.         pop    di
  168.         pop    dx
  169.         pop    cx
  170.         pop    bx
  171.         pop    ax
  172.         pop    bp
  173.         popf
  174.         ret
  175. sl_printff      endp
  176. ;
  177. ;
  178. ;
  179. ;
  180. ; GetEscChar- Handles items immediately following the escape character "\".
  181. ;
  182. ;    Special escape characters (upper/lower case is acceptable):
  183. ;
  184. ;        n    Newline (cr/lf)
  185. ;        t    tab
  186. ;        b    backspace
  187. ;        r    return
  188. ;        l    line feed
  189. ;        f    formfeed
  190. ;        \    \
  191. ;        %    &
  192. ;        0xhh    Char with hex character code hh.  Must have exactly
  193. ;            two hexadecimal digits.
  194. ;
  195. GetEscChar    proc    near
  196.         lodsb            ;Get next character
  197.         cmp    al, 'n'
  198.         je    RtnNL
  199.         cmp    al, 'N'
  200.         je    RtnNL
  201.         cmp    al, 't'
  202.         je    RtnTab
  203.         cmp    al, 'T'
  204.         je    RtnTab
  205.         cmp    al, 'b'
  206.         je    RtnBS
  207.         cmp    al, 'B'
  208.         je    RtnBS
  209.         cmp    al, 'r'
  210.         je    RtnRtn
  211.         cmp    al, 'R'
  212.         je    RtnRtn
  213.         cmp    al, 'l'
  214.         je    RtnLF
  215.         cmp    al, 'L'
  216.         je    RtnLF
  217.         cmp    al, 'f'
  218.         je    RtnFF
  219.         cmp    al, 'F'
  220.         je    RtnFF
  221. ;
  222. ; Check for the presence of a 0xhh value here:
  223. ;
  224.         cmp    al, '0'
  225.         jne    RtnChar
  226.         cmp    byte ptr [si], 'x'
  227.         je    GetHex
  228.         cmp    byte ptr [si], 'X'
  229.         jne    RtnChar
  230. ;
  231. ; Okay, process the hex value here.  Note that exactly two hex digits must
  232. ; follow the 0x.
  233. ;
  234. GetHex:        inc    si        ;Point at first hex digit.
  235.         lodsb            ;Get first hex digit.
  236.         and    al, 05fh    ;l.c. -> u.c.
  237.         cmp    al, 'A'
  238.         jb    GotIt
  239.         sub    al, '7'
  240. GotIt:        shl    al, 1        ;Put into H.O. nibble.
  241.         shl    al, 1
  242.         shl    al, 1
  243.         shl    al, 1
  244.         mov    ah, al        ;Save for later
  245.         lodsb            ;Get next char.
  246.         and    al, 05fh
  247.         cmp    al, 'A'
  248.         jb    GotIt2
  249.         sub    al, '7'
  250. GotIt2:        and    al, 0fh
  251.         or    al, ah
  252.         ret            ;Return hex constant.
  253. ;
  254. ; RtnNL (return Newline) cheats.  It needs to return two characters.
  255. ; Since GetEscChar only returns a single character, this code goes ahead
  256. ; and calls putc to output the CR and the returns the LF.
  257. ;
  258. RtnNL:        mov    al, cr
  259.         call    Putc
  260.         mov    al, lf
  261.         ret
  262. ;
  263. RtnTab:        mov    al, tab
  264.         ret
  265. ;
  266. RtnBS:        mov    al, bs
  267.         ret
  268. ;
  269. RtnRtn:        mov    al, cr
  270.         ret
  271. ;
  272. RtnLF:        mov    al, lf
  273.         ret
  274. ;
  275. RtnFF:        mov    al, ff
  276. RtnChar:    ret
  277. ;
  278. GetEscChar    endp
  279. ;
  280. ;
  281. ;
  282. GetFmtItem    proc    near
  283.         lodsb                ;Get char beyond "%"
  284. ;
  285.         mov    cx, 1            ;Default field width is 1.
  286.         mov    dl, 0            ;Default is right justified
  287.         mov    dh, ' '            ;Default fill char is space.
  288.         mov    ah, ' '            ;Assume straight ptr, not handle.
  289. ;
  290. ; See if the user wants the value left justified:
  291. ;
  292.         cmp    al, '-'
  293.         jne    NotLeftJust
  294.         inc    dl            ;Set to right justified
  295.         lodsb                ;Get next character.
  296. ;
  297. ; See if the user wants to change the padding character.
  298. ;
  299. NotLeftJust:    cmp    al, '\'
  300.         jne    NoPadChange
  301.         lodsb                ;Get Padding Character.
  302.         mov    dh, al            ;Save padding character.
  303.         lodsb                ;Get next character
  304. ;
  305. ; See if the user wants a different field width:
  306. ;
  307. NoPadChange:    cmp    al, '0'
  308.         jb    NoFldWidth
  309.         cmp    al, '9'
  310.         ja    NoFldWidth
  311.         call    GetDecVal
  312. ;
  313. ; See if the user wants to specify a handle rather than a straight pointer
  314. ;
  315. NoFldWidth:    cmp    al, '^'
  316.         jne     ChkFmtChars
  317.         mov    ah, al
  318.         lodsb                ;Skip "^" character
  319. ;
  320. ; Okay, process the format characters down here.
  321. ;
  322. ChkFmtChars:    and    al, 05fh        ;l.c. -> U.C.
  323.         cmp    al, 'D'
  324.         je    PrintDec2
  325.         cmp    al, 'I'
  326.         je    PrintDec2
  327.         cmp    al, 'C'
  328.         je    PrintChar2
  329. ;
  330.         cmp    al, 'X'
  331.         jne    TryH
  332.         jmp    PrintHexWord
  333. ;
  334. PrintDec2:    jmp    PrintDec
  335. PrintChar2:    jmp    PrintChar
  336. TryH:        cmp    al, 'H'
  337.         jne    TryU
  338.         jmp    PrintHexByte
  339. ;
  340. TryU:        cmp    al, 'U'
  341.         jne    TryString
  342.         jmp    PrintUDec
  343. ;
  344. TryString:    cmp    al, 'S'
  345.         jne    TryFloat
  346.         jmp    PrintString
  347. ;
  348. TryFloat:    cmp    al, 'F'
  349.         jne    TrySci
  350.         jmp    PrintSPFP
  351. ;
  352. TrySci:        cmp    al, 'E'
  353.         jne    TryExt
  354.         jmp    PrintSPFPE
  355. ;
  356. TryExt:        cmp    al, 'G'
  357.         jne    TryLong
  358.         lodsb            ;If it's the "G" modifier, look for F/E
  359.         and    al, 05fh    ;l.c. -> U.C.
  360.         cmp    al, 'F'        ;See if GF (ext prec., dec out).
  361.         jne    TryEE
  362.         jmp    PrintDPFP
  363. ;
  364. TryEE:        cmp    al, 'E'        ;See if GE (ext prec, sci not out).
  365.         jne    Default
  366.         jmp    PrintDPFPE
  367. ;
  368. ;
  369. ;
  370. TryLong:    cmp    al, 'L'
  371.         jne    Default
  372. ;
  373. ; If we've got the "L" modifier, this is a long value to print, get the
  374. ; data type character as the next value:
  375. ;
  376.         lodsb
  377.         and    al, 05fh        ;l.c. -> U.C.
  378.         cmp    al, 'D'
  379.         je    JmpDec
  380.         cmp    al, 'I'
  381.         jne    TryLU
  382. JmpDec:        jmp    LongDec
  383. ;
  384. TryLU:        cmp    al, 'U'
  385.         jne    TryX
  386.         jmp    LongU
  387. ;
  388. TryX:        cmp    al, 'X'
  389.         jne    TryLF
  390.         jmp    LongX
  391. ;
  392. TryLF:        cmp    al, 'F'
  393.         jne    TryLE
  394.         jmp     PrintEPFP
  395. ;
  396. TryLE:        cmp    al, 'E'
  397.         jne    Default
  398.         jmp    PrintEPFPE
  399. ;
  400. ;
  401. ; If none of the above, simply return without printing anything.
  402. ;
  403. Default:    ret
  404. ;
  405. ;
  406. ;
  407. PrintSPFP:      call    GetPtr
  408.         xchg    di, bx
  409.         call    sl_LSFPA
  410. DoTheRestf:    mov    ax, cx
  411.         call    putf
  412.         xchg    di, bx
  413.         ret
  414. ;
  415. PrintSPFPE:     call    GetPtr
  416.         xchg    di, bx
  417.         call    sl_LSFPA
  418. DoTheReste:    mov    ax, cx
  419.         call    pute
  420.         xchg    di, bx
  421.         ret
  422. ;
  423. PrintDPFP:    call    GetPtr
  424.         xchg    di, bx
  425.         call    sl_LDFPA
  426.         jmp    DoTheRestf
  427. ;
  428. PrintDPFPE:    call    GetPtr
  429.         xchg    di, bx
  430.         call    sl_LDFPA
  431.         jmp    DoTheReste
  432. ;
  433. PrintEPFP:    call    GetPtr
  434.         xchg    di, bx
  435.         call    sl_LEFPA
  436.         jmp    DoTheRestf
  437. ;
  438. PrintEPFPE:    call    GetPtr
  439.         xchg    di, bx
  440.         call    sl_LEFPA
  441.         jmp    DoTheReste
  442. ;
  443. ;
  444. ;
  445. ; Print a signed decimal value here.
  446. ;
  447. PrintDec:    call    GetPtr            ;Get next pointer into ES:BX
  448.         mov    ax, es:[bx]        ;Get value to print.
  449.         call    ISize            ;Get the size of this guy.
  450.         sub    al, cl            ;Compute padding size
  451.         neg    al
  452.         cbw
  453.         mov    cx, ax
  454.         mov    ax, es:[bx]        ;Retrieve value to print.
  455.         js    NoPadDec        ;Is CX negative?
  456.         cmp    dl, 0            ;Right justified?
  457.         jne    LeftJustDec
  458.         call    PrintPad        ;Print padding characters
  459.         call    Puti            ;Print the integer
  460.         ret                ;We're done!
  461. ;
  462. ; Print left justified value here.
  463. ;
  464. LeftJustDec:    call    Puti
  465.         call    PrintPad
  466.         ret
  467. ;
  468. ; Print non-justified value here:
  469. ;
  470. NoPadDec:    call    Puti
  471.         ret
  472. ;
  473. ;
  474. ;
  475. ; Print a character variable here.
  476. ;
  477. PrintChar:    call    GetPtr            ;Get next pointer into ES:BX
  478.         mov    al, es:[bx]        ;Retrieve value to print.
  479.         mov    ch, 0
  480.         dec    cx
  481.         js    NoPadChar        ;Is CX negative?
  482.         cmp    dl, 0            ;Right justified?
  483.         jne    LeftJustChar
  484.         call    PrintPad        ;Print padding characters
  485.         call    Putc            ;Print the character
  486.         ret                ;We're done!
  487. ;
  488. ; Print left justified value here.
  489. ;
  490. LeftJustChar:    call    Putc
  491.         call    PrintPad
  492.         ret
  493. ;
  494. ; Print non-justified character here:
  495. ;
  496. NoPadChar:    call    Putc
  497.         ret
  498. ;
  499. ;
  500. ;
  501. ;
  502. ; Print a hexadecimal word value here.
  503. ;
  504. PrintHexWord:    call    GetPtr            ;Get next pointer into ES:BX
  505.         mov    ax, es:[bx]        ;Get value to print.
  506.         mov    ch, 0
  507.         sub    cx, 4            ;Compute padding
  508.         js    NoPadHexW        ;Is CX negative?
  509.         cmp    dl, 0            ;Right justified?
  510.         jne    LeftJustHexW
  511.         call    PrintPad        ;Print padding characters
  512.         call    Putw            ;Print the hex value
  513.         ret                ;We're done!
  514. ;
  515. ; Print left justified value here.
  516. ;
  517. LeftJustHexW:    call    Putw
  518.         call    PrintPad
  519.         ret
  520. ;
  521. ; Print non-justified value here:
  522. ;
  523. NoPadHexW:    call    Putw
  524.         ret
  525. ;
  526. ;
  527. ;
  528. ;
  529. ; Print hex bytes here.
  530. ;
  531. ;
  532. PrintHexByte:    call    GetPtr            ;Get next pointer into ES:BX
  533.         mov    ax, es:[bx]        ;Get value to print.
  534.         mov    ch, 0
  535.         sub    cx, 2            ;Compute padding
  536.         js    NoPadHexB        ;Is CX negative?
  537.         cmp    dl, 0            ;Right justified?
  538.         jne    LeftJustHexB
  539.         call    PrintPad        ;Print padding characters
  540.         call    Puth            ;Print the hex value
  541.         ret                ;We're done!
  542. ;
  543. ; Print left justified value here.
  544. ;
  545. LeftJustHexB:    call    Puth
  546.         call    PrintPad
  547.         ret
  548. ;
  549. ; Print non-justified value here:
  550. ;
  551. NoPadHexB:    call    Puth
  552.         ret
  553. ;
  554. ;
  555. ;
  556. ; Output unsigned decimal numbers here:
  557. ;
  558. PrintUDec:    call    GetPtr            ;Get next pointer into ES:BX
  559.         mov    ax, es:[bx]        ;Get value to print.
  560.         call    USize            ;Get the size of this guy.
  561.         mov    ch, 0
  562.         sub    cx, ax                 ;Compute padding
  563.         mov    ax, es:[bx]        ;Retrieve value to print.
  564.         js    NoPadUDec        ;Is CX negative?
  565.         cmp    dl, 0            ;Right justified?
  566.         jne    LeftJustUDec
  567.         call    PrintPad        ;Print padding characters
  568.         call    Putu            ;Print the integer
  569.         ret                ;We're done!
  570. ;
  571. ; Print left justified value here.
  572. ;
  573. LeftJustUDec:    call    Putu
  574.         call    PrintPad
  575.         ret
  576. ;
  577. ; Print non-justified value here:
  578. ;
  579. NoPadUDec:    call    Putu
  580.         ret
  581. ;
  582. ;
  583. ;
  584. ;
  585. ; Output a string here:
  586. ;
  587. PrintString:    call    GetPtr            ;Get next pointer into ES:BX
  588. ;
  589. ; Compute the length of the string:
  590. ;
  591.         push    di
  592.         push    cx
  593.         mov    cx, -1
  594.         mov    di, bx
  595.         mov    al, 0
  596.     repne    scasb
  597.         mov    ax, cx
  598.         neg    ax
  599.         dec    ax
  600.         dec    ax
  601.         pop    cx
  602.         pop    di
  603.         mov    ch, 0
  604.         sub    cx, ax            ;Field width - String Length.
  605. ;
  606.         js    NoPadStr        ;Is CX negative?
  607.         cmp    dl, 0            ;Right justified?
  608.         jne    LeftJustStr
  609.         call    PrintPad        ;Print padding characters
  610.         call    Puts            ;Print the string
  611.         ret                ;We're done!
  612. ;
  613. ; Print left justified value here.
  614. ;
  615. LeftJustStr:    call    Puts
  616.         call    PrintPad
  617.         ret
  618. ;
  619. ; Print non-justified value here:
  620. ;
  621. NoPadStr:    call    Puts
  622.         ret
  623. GetFmtItem    endp
  624. ;
  625. ;
  626. ;
  627. ; Print a signed long decimal value here.
  628. ;
  629. LongDec:    call    GetPtr            ;Get next pointer into ES:BX
  630.         mov    ax, es:[bx]        ;Get value to print.
  631.         push    dx
  632.         mov    dx, es:2[bx]
  633.         call    LSize            ;Get the size of this guy.
  634.         pop    dx
  635.         mov    ch, 0
  636.         sub    cx, ax                 ;Compute padding
  637.         mov    ax, es:[bx]        ;Retrieve value to print.
  638.         js    NoPadLong        ;Is CX negative?
  639.         cmp    dl, 0            ;Right justified?
  640.         jne    LeftJustLong
  641.         call    PrintPad        ;Print padding characters
  642.         mov    dx, es:2[bx]        ;Get H.O. word
  643.         call    PutL            ;Print the integer
  644.         ret                ;We're done!
  645. ;
  646. ; Print left justified value here.
  647. ;
  648. LeftJustLong:    push    dx
  649.         mov    dx, es:2[bx]        ;Get H.O. word
  650.         call    PutL
  651.         pop    dx
  652.         call    PrintPad
  653.         ret
  654. ;
  655. ; Print non-justified value here:
  656. ;
  657. NoPadLong:    mov    dx, es:2[bx]        ;Get H.O. word
  658.         call    Putl
  659.         ret
  660. ;
  661. ;
  662. ; Print an unsigned long decimal value here.
  663. ;
  664. LongU:        call    GetPtr            ;Get next pointer into ES:BX
  665.         mov    ax, es:[bx]        ;Get value to print.
  666.         push    dx
  667.         mov    dx, es:[bx]
  668.         call    ULSize            ;Get the size of this guy.
  669.         pop    dx
  670.         mov    ch, 0
  671.         sub    cx, ax                 ;Compute padding
  672.         mov    ax, es:[bx]        ;Retrieve value to print.
  673.         js    NoPadULong        ;Is CX negative?
  674.         cmp    dl, 0            ;Right justified?
  675.         jne    LeftJustULong
  676.         call    PrintPad        ;Print padding characters
  677.         mov    dx, es:2[bx]        ;Get H.O. word
  678.         call    PutUL            ;Print the integer
  679.         ret                ;We're done!
  680. ;
  681. ; Print left justified value here.
  682. ;
  683. LeftJustULong:    push    dx
  684.         mov    dx, es:2[bx]        ;Get H.O. word
  685.         call    PutUL
  686.         pop    dx
  687.         call    PrintPad
  688.         ret
  689. ;
  690. ; Print non-justified value here:
  691. ;
  692. NoPadULong:    mov    dx, es:2[bx]        ;Get H.O. word
  693.         call    Putul
  694.         ret
  695. ;
  696. ;
  697. ; Print a long hexadecimal value here.
  698. ;
  699. LongX:        call    GetPtr            ;Get next pointer into ES:BX
  700.         mov    ch, 0
  701.         sub    cx, 8            ;Compute padding
  702.         js    NoPadXLong        ;Is CX negative?
  703.         cmp    dl, 0            ;Right justified?
  704.         jne    LeftJustXLong
  705.         call    PrintPad        ;Print padding characters
  706.         mov    ax, es:2[bx]        ;Get H.O. word
  707.         call    Putw
  708.         mov    ax, es:[bx]
  709.         call    Putw
  710.         ret                ;We're done!
  711. ;
  712. ; Print left justified value here.
  713. ;
  714. LeftJustxLong:    mov    ax, es:2[bx]        ;Get H.O. word
  715.         call    Putw
  716.         mov    ax, es:[bx]        ;Get L.O. word
  717.         call    Putw
  718.         call    PrintPad
  719.         ret
  720. ;
  721. ; Print non-justified value here:
  722. ;
  723. NoPadxLong:    mov    ax, es:2[bx]        ;Get H.O. word
  724.         call    Putw
  725.         mov    ax, es:[bx]
  726.         call    Putw
  727.         ret
  728. ;
  729. ;
  730. ;
  731. ;
  732. ; Puts- Outputs the zero terminated string pointed at by ES:BX.
  733. ;
  734. Puts        proc    near
  735. PutsLp:        mov    al, es:[bx]
  736.         cmp    al, 0
  737.         je    PutsDone
  738.         call    putc
  739.         inc    bx
  740.         jmp    PutsLp
  741. ;
  742. PutsDone:    ret
  743. Puts        endp
  744. ;
  745. ;
  746. ;
  747. ;
  748. ;
  749. ; PrintPad-    Prints padding characters.  Character to print is in DH.
  750. ;        We must print it CX times.  CX must be greater than zero.
  751. ;
  752. PrintPad    proc    near
  753.         push    ax
  754.         mov    al, dh
  755.         jcxz    NoPadding
  756. PPLoop:        call    Putc
  757.         loop    PPLoop
  758. NoPadding:    pop    ax
  759.         ret
  760. PrintPad    endp
  761. ;
  762. ;
  763. ;
  764. ;
  765. ;
  766. ; GetPtr- Grabs the next pointer which DS:DI points at and returns this
  767. ;      far pointer in ES:BX.
  768. ;
  769. GetPtr        proc    near
  770.         les    bx, [di]
  771.         add    di, 4
  772. ;
  773. ; See if this is a handle rather than a pointer.
  774. ;
  775.         cmp    ah, '^'
  776.         jne    NotHandle
  777.         les    bx, es:[bx]
  778. NotHandle:    ret
  779. GetPtr        endp
  780. ;
  781. ;
  782. ;
  783. ;
  784. ;
  785. ; GetDecVal-    Converts the string of decimal digits in AL and [SI] into
  786. ;        an integer and returns this integer in CL/CH.
  787. ;
  788. GetDecVal    proc    near
  789.         push    dx
  790.         dec    si
  791.         xor    cx, cx
  792. DecLoop:    lodsb
  793.         cmp    al, '0'
  794.         jb    NoMore
  795.         cmp    al, '9'
  796.         ja    NoMore
  797.         and    al, 0fh
  798.         shl    cl, 1            ;Compute CL := CL*10 + al
  799.         mov    dl, cl
  800.         shl    cl, 1
  801.         shl    cl, 1
  802.         add    cl, dl
  803.         add    cl, al
  804.         jmp    DecLoop
  805. ;
  806. NoMore:        cmp    al, '.'
  807.         jne    ReallyNoMore
  808. ;
  809. ; User entered nnn.nnn here.  Process for floating point values:
  810. ;
  811. DecLoop2:    lodsb
  812.         cmp    al, '0'
  813.         jb    ReallyNoMore
  814.         cmp    al, '9'
  815.         ja    ReallyNoMore
  816.         and    al, 0fh
  817.         shl    ch, 1            ;Compute CX := CX*10 + al
  818.         mov    dh, ch
  819.         shl    ch, 1
  820.         shl    ch, 1
  821.         add    ch, dh
  822.         add    ch, al
  823.         jmp    DecLoop2
  824. ;
  825. ReallyNoMore:    pop    dx
  826.         ret
  827. GetDecVal    endp
  828. ;
  829. stdlib        ends
  830.         end
  831.